「초심자」무작정 해보는 ECS 컨테이너 서비스 구축 – 2 (ECS 구축)
안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다.「무작정 해보는 ECS 컨테이너 서비스 구축」과정의 두 번째로 이번에는 클러스터를 생성하고, 작업 정의를 통해 ECS를 구축하는 과정을 정리해 봤습니다.
이전 내용은 아래 블로그를 참고해 주세요.
클러스터 생성
먼저 클러스터를 생성하기 전에 NAT Gateway를 생성할 필요가 있습니다. 현재 클러스터를 생성하고, EC2 인스턴스를 Private Subnet에 배치 할 생각이기 때문에 NAT Gateway를 통해 Private Subnet의 인스턴스가 인터넷에 연결할 수 있도록 해야합니다.
NAT Gateway를 생성하지 않고 클러스터를 생성해 보면 EC2는 정상적으로 움직이고 있는 것을 확인할 수 있지만
클러스터를 확인해 보면 Private Subnet에 있는 EC2 인스턴스를 인식할 수 없는 것을 볼 수 있습니다.
NAT Gateway 생성을 위해 VPC로 들어간 다음, 왼쪽 카테고리에서「NAT 게이트웨이」를 클릭하고 오른쪽에 있는「NAT 게이트웨이 생성」버튼을 클릭합니다.
NAT Gateway는 Private Subnet 인스턴스를 인터넷에 연결해야 하기 때문에 Public Subnet에 배치해야 합니다.
이어서 생성한 탄력적 IP가 없다면「탄력적 IP 할당」버튼을 클릭하고 NAT Gateway 생성을 끝마칩니다.
이제 라우팅 테이블에서 NAT Gateway를 추가합니다.
- 0.0.0.0
- NAT Gateway 선택
을 하고「변경 사항 저장」버튼을 클릭하면 NAT Gateway에 대한 설정이 끝납니다.
이제 클러스터를 생성해 보도록 하겠습니다. 먼저 ECS 서비스에서「클러스터」카테고리를 클릭한 다음「클러스터 생성」버튼을 클릭합니다.
EC2 리눅스를 선택하고 다음 단계로 넘어갑니다.
클러스터 이름은「ecs-nginx」로 입력하고 온디맨드를 선택합니다.
EC2 인스턴스 유형은 Dockerfile 크기에 따라 적절하게 선택해주시면 됩니다. 지금은 nginx만 설치하는 작업이기 때문에 용량이 크지 않은 관계로 t2 유형을 선택했습니다. t2 유형은 비용이 저렴한 범용 인스턴스 유형입니다. 그외에 인스턴스 개수는 2개로 입력하고 키페어는 없음으로 진행합니다.
인스턴스 유형에 관한 정보는 아래 블로그를 참고해 주세요.
VPC는 이전에 만들어 두었던「ecs-vpc」를 선택합니다. 서브넷은 private subnet을 선택하고, IP 할당은 비활성화를 선택합니다. 마지막으로 보안 그룹은 ecs-container-sg를 선택합니다.
IAM Role의 경우「Create new role」을 클릭하면「ecsinstanceRole」이라는 이름으로 IAM Role이 자동으로 생성 됩니다. 마지막으로 생성 버튼을 클릭해서 클러스터 생성을 끝마칩니다.
이제 클러스터를 확인해 보면 NAT Gateway를 통해 Private Subnet의 EC2 인스턴스를 인식하는 것을 볼 수 있습니다.
작업 정의(Task definition)
이어서 새 작업 정의를 진행 해야합니다. 작업 정의에서 로드 밸런서를 선택할 필요가 있기 때문에 먼저 로드 밸런서를 생성하는 작업부터 하고자 합니다.
ALB 생성
먼저 로드 밸런서 카테고리를 클릭하고「로드 밸런서 생성」버튼을 클릭합니다.
ALB를 선택합니다.
로드 밸런서 이름을「ecs-alb」로 입력합니다.
VPC는 ecs-vpc를 선택하고 Subnet은 퍼블릭 서브넷을 선택합니다.
보안 그룹은「ecs-alb-sg」를 선택합니다. 그리고 타겟 그룹을 생성하기 위해「Create target group」을 클릭합니다.
타겟 그룹 이름만 적어주고 타겟 그룹 생성을 끝마칩니다. 여기서 타겟 그룹에 현재 생성된 EC2는 추가하지 않고 생성합니다.
클러스터 생성을 통해 만들어진 EC2 인스턴스 2개를 추가하고 타겟 그룹 생성을 끝마칩니다.
다시 ALB 생성으로 돌아와서 조금 전 생성한 ecs-target-group을 추가하고 ALB 생성을 끝마칩니다.
작업 정의(Task definition) 생성
다시 ECS로 돌아와서「새 작업 정의 생성」버튼을 클릭합니다.
이번 블로그에서는 Fargate가 아닌 EC2만 다룰 예정입니다. (추후 Fargate도 다뤄보도록 하겠습니다.)
테스크 이름은「ecs-nginx-task」로 입력허고 네트워크 모드는「브리지」를 선택합니다.
네트워크 모드는 브리지, 호스트, awsvpc, 없음이 있습니다.
- 브리지 : 가상 네트워크 브리지를 사용하여 호스트와 컨테이너의 네트워킹 사이에 레이어를 만듭니다. 이렇게하면 호스트 포트를 컨테이너 포트에 다시 매핑하는 포트 매핑을 만들 수 있습니다. 매핑은 정적 또는 동적일 수 있습니다. 하지만 각 호스트에서 태스크의 인스턴스화를 하나 이상 실행할 수 없습니다. 이는 정적 포트 매핑이 단일 컨테이너 만 포트 80에 매핑 할 수 있기 때문 입니다. 포트 매핑에 호스트 포트를 지정하지 않으면 Docker가 임시 포트 범위에서 사용되지 않는 임의의 포트를 선택하여 컨테이너의 공용 호스트 포트로 할당하도록 할 수 있습니다.
- 호스트 : 컨테이너는 기본 호스트 Amazon EC2 인스턴스의 IP 주소를 사용하여 ex)포트 3000에서 트래픽을 수신, 각 호스트에서 태스크의 인스턴스화를 하나 이상 실행할 수 없습니다.
- awsvpc : Amazon ECS는 각 작업에 대해 ENI (엘라스틱 네트워크 인터페이스) 를 생성 및 관리하며, 각 작업은 VPC 내에서 자체 프라이빗 IP 주소를 받습니다. 이 ENI는 기본 호스트 ENI와 별개입니다. Amazon EC2 인스턴스에서 여러 작업을 실행하는 경우 각 작업의 ENI도 별개입니다.
- 없음 : 포트 매핑 불가, 외부와 연결 X
그리고「컨테이너 추가」버튼을 클릭합니다.
이미지에는 ECR에서 Image URI를 복사해서 넣습니다.
메모리 제한은 512를 입력하고 컨테이너 포트는 호스트 포트0, 컨테이너 포트80을 입력합니다. 호스트 포트를 지정할 경우 각 호스트에서 태스크의 인스턴스화를 하나 이상 실행할 수 없습니다. 정적 포트 매핑이 단인 컨테이너 포트 80에만 매핑 할 수 있기 때문입니다.
- 동적 매핑 -> 상황에 따라 매핑을 시도함
- 정적 매핑 -> 지정된 곳에만 매핑을 시도함
호스트 포트를 0(없음)으로 지정하면 컨테이너 인스턴스의 임시 포트 범위(예: 최신 Amazon ECS-optimized AMI에서 32768 ~ 61000)에서 호스트 포트가 동적으로 선택 됩니다.
동적 포트 매핑을 사용하는 경우 호스트 포트를 0으로 설정하면 에페메랄 포트(32768-61000) 범위의 포트가 자동으로 할당되며 alb에 설정해놓은 target group의 포트는 무시됩니다.
서비스 생성
이어서 클러스터로 들어온 다음 서비스 카테고리에서「생성」버튼을 클릭합니다.
시작 유형은 EC2로 선택하고 서비스 이름을 적어줍니다. 서브스 유형 Replica는 설정한 작업 개수만큼 테스크를 복제하여 실행하고, Deamon 유형은 클러스터에 연결된 인스턴스 하나당 하나의 task만 실행합니다.
예를들어 작업 개수를 2로 설정한경우 2개의 테스크를 실행합니다.
로드 밸런서는 ALB를 선택하고, 「AWSServiceRoleForECS」역할과 조금 전 생성 했던 로드 밸런서를 선택합니다.
그리고「로드 밸런서 추가」버튼을 클릭해서 로드 밸런서를 추가합니다. 대상 그룹 이름을 선택하면 나머지는 자동으로 채워집니다.
이후 오토 스케일링은 선택하지 않고 이대로 서비스 생성을 끝마칩니다.
타겟 그룹을 확인해 보면 49153 포트 번호로 EC2 인스턴스가 추가된 것을 확인할 수 있습니다. 조금전에 설명했던 것 처럼 동적 포트 매핑을 사용하는 경우 호스트 포트를 0으로 설정하면 에페메랄 포트(32768-61000) 범위의 포트가 자동으로 할당되며 alb에 설정해놓은 target group의 포트는 무시됩니다.
이제 alb dns로 접속해 보면 성공적으로 웹 페이지가 출력되는 것을 확인할 수 있습니다.
ECS 컨테이너에 접속
EC2 인스턴스에 연결되어 있는 ecsInstanceRole을 수정해서「Amazon EC2RoleforSSM」을 추가합니다.
그리고「Session Manager」탭을 클릭하고 연결 버튼을 클릭하면 Private Subnet의 EC2로 접속할 수 있습니다.
cd /var/lib/docker/overlay2
docker는 다음 경로에 설치되어 있습니다.
diff에는 베이스로 설치한 nginx가 들어있고, merged에는 nginx와 추가로 작업을 진행 했던 hello ecs! 의 작업 내용들이 들어있습니다.
merged에 있는 index.html을 확인해 보면 dockerfile을 생성할 때 설정했던 index.html가 들어있는 것을 확인할 수 있습니다.
h1태그를 "first ec2 ecs"로 수정해서 재접속해 보면
first ec2 ecs와 hello ecs!가 번갈아가면서 출력되는 것을 확인할 수 있습니다.